﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BFlatCompile.Project
{
	internal static class ProjectUtil
	{
		public static string[] FlattenCompileTargets(string projectDir, JsonObject root)
		{
			return FlattenTargets(projectDir, root, "compile");
		}

		public static string[] FlattenCopyTargets(string projectDir, JsonObject root)
		{
			return FlattenTargets(projectDir, root, "copy");
		}

		private static string[] FlattenTargets(string projectDir, JsonObject root, string type)
		{
			JsonList list = root.TryGetList("files");
			if (list == null)
			{
				return new string[0];
			}

			List<string> output = new List<string>();
			foreach (JsonObject fileClump in list.Items.OfType<JsonObject>())
			{
				if (fileClump.TryGetString("action") == type)
				{
					string filePattern = fileClump.TryGetString("filename");
					GetAllFiles(projectDir, filePattern, output);
				}
			}

			return output.ToArray();
		}

		private static void GetAllFiles(string currentDirectory, string pattern, List<string> output)
		{
			if (pattern.Contains('/'))
			{
				int index = pattern.IndexOf('/');
				string folder = pattern.Substring(0, index);
				string rest = pattern.Substring(index + 1);
				List<string> folderList = new List<string>();
				if (folder == "**")
				{
					if (rest.Contains('/'))
					{
						throw new Exception("Invalid file pattern.");
					}

					GetAllFolders(currentDirectory, folderList);
					folderList.Add(currentDirectory);
					foreach (string directory in folderList)
					{
						GetAllMatchingFilesInFolder(directory, rest, output);
					}
				}
				else
				{
					string fullPath = System.IO.Path.Combine(currentDirectory, folder);
					if (System.IO.Directory.Exists(fullPath))
					{
						GetAllFiles(fullPath, rest, output);
					}
					else
					{
						throw new Exception("Path does not exist.");
					}
				}
			}
			else
			{
				GetAllMatchingFilesInFolder(currentDirectory, pattern, output);
			}
		}

		private static void GetAllMatchingFilesInFolder(string folder, string pattern, List<string> output)
		{
			foreach (string file in System.IO.Directory.GetFiles(folder))
			{
				bool match;
				if (pattern == "*")
				{
					match = true;
				}
				else if (pattern.StartsWith("*"))
				{
					match = file.ToLowerInvariant().EndsWith(pattern.Substring(1));
				}
				else if (pattern.EndsWith("*"))
				{
					match = file.ToLowerInvariant().StartsWith(pattern.Substring(0, pattern.Length - 1));
				}
				else
				{
					throw new NotImplementedException("Need to look up regular expression when I get wifi.");
				}

				if (match)
				{
					string fullPath = System.IO.Path.Combine(folder, file);
					output.Add(fullPath);
				}
			}
		}

		private static void GetAllFolders(string currentDirectory, List<string> output)
		{
			foreach (string folder in System.IO.Directory.GetDirectories(currentDirectory))
			{
				string fullPath = System.IO.Path.Combine(currentDirectory, folder);
				output.Add(fullPath);
				GetAllFolders(fullPath, output);
			}
		}
	}
}
